經過前面漫長的鋪陳,差不多是時候來進行SPA完整的實做了,接下來我們就來試試用Node搭配原生JS建立單頁應用網站吧!
這邊我們先新建一個專案資料夾,用編輯器開啟資料夾後,我們第一步先做Node專案初始設定:
//快速建立package.json
npm init -y
專案建立之後,在目錄下面只會有一個package.json。接著我們新增主頁面,並放置在主路徑下:
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>SPA with Router</title>
</head>
<body>
</body>
</html>
為了區別開發與發布版本,這邊我們建立了兩個資料夾:
上述可再src/dist依照檔案類型建立其他資料夾做區分。另外在src路徑下建立index.js,用來做SPA的進入點,等等會用到。
這邊所列的安裝項目是本專案開發會用到的,主要會搭配webpack進行打包與編譯:
安裝webpack和webpack-cli套件:
npm install webpack webpack-cli --save-dev
在主目錄建立webpack.config.js設定檔:
webpack.config.js:
const path = require("path");
module.exports = {
mode: "development", //開發模式(預設為發布)
entry: "./src/index.js", //SPA進入點
watch: true, //監聽變動設置
output: {
filename: "index.bundle.js", //輸出檔名
path: path.resolve(__dirname, "dist"), //輸出位置
},
};
另外記得在package.json的scripts建立build指令,用來啟動webpack:
package.json:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack", //npm run build,執行webpack指令
},
這樣在終端器輸入npm run build就可以執行了,因為帶有watch監聽的設定,所以檔案變動同時都會重新跑一次。
babel是一個轉譯器、編譯器,當開發者使用 ES6以上的語法,會自動轉換成舊版本的Javascript,讓低版本的瀏覽器也能相容運作。以下來安裝babel-loader套件:
npm install babel-loader @babel/core @babel/preset-env --save-dev
然後我們到webpack設定檔,加入以下設定就可以了:
webpack.config.js:
module.exports = {
...
,
module: {
rules: [
{
test: /\.(js)$/,
exclude: /(node_modules)/,
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-env"],
},
},
},
],
},
...
scss具有階層化與結合程式寫法的特點,非常適合前端開發者進行樣式撰寫。但因為瀏覽器無法識別scss,所以需要將scss做預處理並轉換為css檔案:
npm install sass-loader node-sass css-loader mini-css-extract-plugin --save-dev
安裝完畢後一樣去webpack設定檔加入以下設定:
webpack.config.js:
const path = require("path");
//引入
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module: {
rules: [
{...},
{
test: /\.(scss|sass)$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
},
],
},
plugins: [new MiniCssExtractPlugin({
filename: 'style.css', //轉換css檔名(預設為main.css)
})],
以上全部安裝設定後,接著就來試試看成果。
我們到src資料夾裡的index.js,並在內容輸入程式,來測試babel是否可以將ES6的語法做轉換:
src/index.js:
//ES6 const常數宣告
const hello = `<h1 class="hello">Hello,world!</h1>`;
document.querySelector("#wrapper").innerHTML = hello;
輸入完畢後在終端器執行npm run build,然後到dist資料夾下查看index.bundle.js這隻檔案的最末段,來看看剛剛的打包是否對es6的const宣告做轉換:
可以看到const有轉換成var宣告,正常運作。
接著我們到src資料夾下建立style.scss,來測試是否能轉換為css檔案:
src/style.scss:
$primary: #0066cc;
.hello {
color: $primary;
}
然後回到index.js裡,第一行引入scss檔案,以便webpack轉換scss模組:
src/index.js:
import "./style.scss";
const hello = `<h1 class="hello">Hello,world!</h1>`;
document.querySelector("#wrapper").innerHTML = hello;
這時再回到dist資料夾查看,發現產生style.css檔案,並且已經是處理過帶入變數的css,代表轉換沒問題!
然後回到主目錄的index.html,引入dist資料夾下的css與js,來看看最終成果:
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>SPA with Router</title>
<link rel="stylesheet" href="./dist/style.css" />
</head>
<body>
<div id="wrapper"></div>
<script src="./dist/index.bundle.js"></script>
</body>
</html>
到這邊算是告一個段落,明天開始來建立第一個Component,為了SPA繼續努力!
參考資料:
測試cscc轉譯css
cscc
好像是筆誤,應該是想打 scss 嗎 XD
對...是個筆誤,感謝指正XD